/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * File Name          : freertos.c
 * Description        : Code for freertos applications
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2023 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include "stdlib.h"
#include "stdbool.h"
#include "usart.h"
#include "tim.h"
#include "mutex.h"
#include "log.h"
#include "rtc.h"
#include "iwdg.h"
#include "key.h"
#include "st7735.h"
#include "menu.h"
#include "ws2812b.h"
#include "adc.h"
#include "adc_convert.h"
#include "pid_ctrl.h"

const static char *TAG = "freertos.c";
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
RTC_DateTypeDef sdatestructureget;
RTC_TimeTypeDef stimestructureget;

KEY_GPIO key_gpio = {GPIOB, GPIO_PIN_2, GPIOB, GPIO_PIN_1, GPIOB, GPIO_PIN_0};
KEY key[KEY_NUM] = {false};
KEY_MSG key_msg = {0};

menu_show_data_t menu_show_data = {
    .menu_a = {12},
    .menu_b = {0},
    .menu_c = {0}};

WS2812B ws2812_demo;
uint32_t ADC1_Value_DMA[2];
ADC_CONVERT convert_data = {6666, 2553, 1024, 65536};
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
    .name = "defaultTask",
    .stack_size = 128 * 4,
    .priority = (osPriority_t)osPriorityNormal,
};
/* Definitions for userTask02 */
osThreadId_t userTask02Handle;
const osThreadAttr_t userTask02_attributes = {
    .name = "userTask02",
    .stack_size = 128 * 4,
    .priority = (osPriority_t)osPriorityNormal5,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
static void task1_init_peripheral(void)
{
    if (HAL_UART_Receive_IT(&huart1, (uint8_t *)(usart1_data.rx_buf + usart1_data.rx_index), 1) != HAL_OK) /* start uart1 interrupt */
    {
        /* error handler begin */
        error_handler_msg_log(__FILE__, __func__);
        error_handler();
        /* error handler end */
    }
    else
    {
        MY_LOGI(TAG, "HAL_UART_Receive_IT init successful!\r\n");
    }

    if (ST7735_Init(&htim10, TIM_CHANNEL_1, 400) != HAL_OK) /* init LCD */
    {
        /* error handler begin */
        error_handler_msg_log(__FILE__, __func__);
        error_handler();
        /* error handler end */
    }
    else
    {
        MY_LOGI(TAG, "ST7735_Init init successful!\r\n");
    }

    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&ADC1_Value_DMA, 2) != HAL_OK) /* start init ADC_DMA */
    {
        /* error handler begin */
        error_handler_msg_log(__FILE__, __func__);
        error_handler();
        /* error handler end */
    }
    else
    {
        MY_LOGI(TAG, "ADC_DMA_Init successful!\r\n");
    }
}
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);
void StartUserTask02(void *argument);

extern void MX_USB_DEVICE_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
 * @brief  FreeRTOS initialization
 * @param  None
 * @retval None
 */
void MX_FREERTOS_Init(void)
{
    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* USER CODE BEGIN RTOS_MUTEX */
    create_mutex(); /* create mutexes */
                    /* add mutexes, ... */
    /* USER CODE END RTOS_MUTEX */

    /* USER CODE BEGIN RTOS_SEMAPHORES */
    /* add semaphores, ... */
    /* USER CODE END RTOS_SEMAPHORES */

    /* USER CODE BEGIN RTOS_TIMERS */
    /* start timers, add new ones, ... */
    /* USER CODE END RTOS_TIMERS */

    /* USER CODE BEGIN RTOS_QUEUES */
    /* add queues, ... */
    /* USER CODE END RTOS_QUEUES */

    /* Create the thread(s) */
    /* creation of defaultTask */
    defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

    /* creation of userTask02 */
    userTask02Handle = osThreadNew(StartUserTask02, NULL, &userTask02_attributes);

    /* USER CODE BEGIN RTOS_THREADS */
    /* add threads, ... */
    /* USER CODE END RTOS_THREADS */

    /* USER CODE BEGIN RTOS_EVENTS */
    /* add events, ... */
    /* USER CODE END RTOS_EVENTS */
}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
 * @brief  Function implementing the defaultTask thread.
 * @param  argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
    /* init code for USB_DEVICE */
    MX_USB_DEVICE_Init();
    /* USER CODE BEGIN StartDefaultTask */
    task1_init_peripheral(); /* init task1 peripheral */
    /* Infinite loop */
    for (;;)
    {
        /* 按键扫描 */
        key_scan(&key_gpio, &key_msg, key);
        /* 多级菜单 */
        main_menu(&key_msg, &menu_show_data);
        menu_show_data.menu_a.a_num += 1;
        menu_show_data.menu_b.b_num += 1;
        menu_show_data.menu_a.adc_channel1 = (float)(ADC1_Value_DMA[0] & 0xFFF) * 3.3f / 4096.0f;
        menu_show_data.menu_a.adc_channel2 = (float)(ADC1_Value_DMA[1] & 0xFFF) * 3.3f / 4096.0f;
        vTaskDelay(pdMS_TO_TICKS(20));
    }
    /* USER CODE END StartDefaultTask */
}

/* USER CODE BEGIN Header_StartUserTask02 */
/**
 * @brief Function implementing the userTask02 thread.
 * @param argument: Not used
 * @retval None
 */
/* USER CODE END Header_StartUserTask02 */
void StartUserTask02(void *argument)
{
    /* USER CODE BEGIN StartUserTask02 */
    uint16_t feed_num = 0;

    set_led(&ws2812_demo, 0, 200, 50, 20);
    set_led(&ws2812_demo, 1, 20, 200, 40);
    set_led(&ws2812_demo, 2, 40, 20, 200);
    set_led(&ws2812_demo, 3, 40, 200, 20);
    set_led(&ws2812_demo, 4, 200, 20, 40);
    set_led(&ws2812_demo, 5, 20, 200, 40);
    set_led(&ws2812_demo, 6, 40, 20, 200);
    set_led(&ws2812_demo, 7, 200, 200, 200);
    /* Infinite loop */
    for (;;)
    {
        // convert(&convert_data);
        // MY_LOGI(TAG, "Channel_0 ADC:%.3f  Channel_1 ADC:%.3f  Vbat Channel ADC:%.3f\r\n", Channel_0, Channel_1, Channel_2);
        breathing_lamps_demo(&htim4, TIM_CHANNEL_2, &ws2812_demo);
        MY_LOGI(TAG, "Feed IWDG! %d\r\n", feed_num++);
        HAL_IWDG_Refresh(&hiwdg); /* 1s feed dog */
    }
    /* USER CODE END StartUserTask02 */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */
